<!DOCTYPE HTML>

<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>SlickGrid example 5: Collapsing</title>
    <link rel="stylesheet" href="../slick.grid.css" type="text/css" />
    <link rel="stylesheet" href="../controls/slick.pager.css" type="text/css" />
    <link rel="stylesheet" href="../plugins/slick.headermenu.css" type="text/css" />
    <link rel="stylesheet" href="../plugins/slick.headerbuttons.css" type="text/css" />
    <link rel="stylesheet" href="../css/smoothness/jquery-ui.css" type="text/css" />
    <link rel="stylesheet" href="examples.css" type="text/css" />
    <link rel="stylesheet" href="../css/select2.css" type="text/css" />
    <link rel="stylesheet" href="../plugins/slick.gantt.css"/>

    <style>
        .select2-container {
            top: -3px;
            left: -6px;
        }

        .select2-container .select2-selection--single {
            height: 30px;
        }

        .icon-highlight-off,
        .icon-highlight-on {
            background-image: url(../images/bullet_blue.png);
        }

        .icon-highlight-off {
            opacity: 0.2;
        }

        .negative-highlight {
            background: red;
        }

        .cell-title {
            font-weight: bold;
        }

        .cell-effort-driven {
            text-align: center;
        }

        .toggle {
            height: 9px;
            width: 9px;
            display: inline-block;
        }

        .toggle.expand {
            background: url(../images/expand.gif) no-repeat center center;
        }

        .toggle.collapse {
            background: url(../images/collapse.gif) no-repeat center center;
        }

        .slick-header-menu {
            border: 1px solid #718BB7;
            background: #f0f0f0;
            padding: 2px;
            -moz-box-shadow: 2px 2px 2px silver;
            -webkit-box-shadow: 2px 2px 2px silver;
            min-width: 100px;
            z-index: 20;
        }

        .slick-header-menuitem {
            padding: 2px 4px;
            border: 1px solid transparent;
            border-radius: 3px;
        }

        .slick-header-menuitem:hover {
            border-color: silver;
            background: white;
        }

        .slick-header-menuitem-disabled {
            border-color: transparent !important;
            background: inherit !important;
        }

        #contextMenu {
            background: #e1efc7;
            border: 1px solid gray;
            padding: 2px;
            display: inline-block;
            min-width: 100px;
            -moz-box-shadow: 2px 2px 2px silver;
            -webkit-box-shadow: 2px 2px 2px silver;
            z-index: 9999;
        }

        #contextMenu li {
            padding: 4px 4px 4px 14px;
            list-style: none;
            cursor: pointer;
            background: url("../images/arrow_right_peppermint.png") no-repeat center left;
        }

        #contextMenu li:hover {
            background-color: white;
        }

        /*定位*/
        .changed {
            background: pink;
        }

        .current {
            border: 1px solid black;
            background: orange;
        }
    </style>
</head>

<body>
    <table width="100%">
        <tr>
            <td valign="top" width="80%">
                <div style="position:relative">
                    <div class="grid-header" style="width:100%">
                        <label>stone slick-grid</label>
                        <span style="float:right" class="ui-icon ui-icon-search" title="Toggle search panel"
                            onclick="toggleFilterRow()"></span>
                    </div>

                    <div id="myGrid" style="width:100%;height:500px;;"></div>
                    <div id="pager" style="width:100%;height:20px;"></div>

                    <div id="inlineFilterPanel" style="display:none;background:transparent;padding:3px;color:black;">
                        Filter: <input type="text" id="txtSearch2">
                        Position:<input type="text" id="txtPosition"><a>Q</a>
                        <a>导出EXCEL</a>
                    </div>
                </div>
            </td>
            </td>
            <td valign="top">
                <h2>Demonstrates:</h2>
                <ul>
                    <li>implementing expand/collapse as a filter for DataView</li>
                </ul>

                <h2>View Source:</h2>
                <ul>
                    <li><A href="https://github.com/mleibman/SlickGrid/blob/gh-pages/examples/example5-collapsing.html"
                            target="_sourcewindow"> View the source for this example on Github</a></li>
                </ul>

                <h2>TODO:</h2>
                <ul>
                    <li>2021-02-24 22:55 gantt 雏形</li>
                    <li>2021-03-07 21:34 gantt 连线雏形</li>
                </ul>
            </td>
        </tr>
    </table>
    <ul id="contextMenu" style="display:none;position:absolute">
        <b>操作:</b>
        <li id='excel' data="excel">export excel</li>
        <li id='scrollRowIntoView' data="search"><input id='scrollRowIntoViewSearch' type="input" style="width: 100px;"
                value="1" />
            <input id='scrollRowIntoViewQuery' type="button" value="Q" />
        </li>
        <li id='addRow'>add row</li>
        <li id='level' data="level">
            <select id='levelOp'>
                <option>ALL</option>
                <option>1</option>
                <option>2</option>
                <option>3</option>
                <option>4</option>
                <option>5</option>
                <option>6</option>
                <option>7</option>
                <option>8</option>
                <option>9</option>
            </select>
        </li>
    </ul>
    <!--https://github.com/rainabba/jquery-table2excel-->
    <script src="../lib/firebugx.js"></script>

    <script src="../lib/jquery-1.7.min.js"></script>

    <script src="../lib/jquery.event.drag-2.2.js"></script>
    <script src="../lib/jquery-ui.min.js"></script>
    <script src="../slick.core.js"></script>
    <script src="../slick.formatters.js"></script>
    <script src="../slick.editors.js"></script>
    <script src="../slick.grid.js"></script>
    <script src="../slick.dataview.js"></script>
    <script src="../plugins/slick.autotooltips.js"></script>
    <script src="../plugins/slick.cellcopymanager.js"></script>
    <script src="../plugins/slick.cellrangedecorator.js"></script>
    <script src="../plugins/slick.cellrangeselector.js"></script>
    <script src="../plugins/slick.gantt.selectionmodel.js"></script>
    <script src="../plugins/slick.gantt.rangeselector.js"></script>
    <script src="../plugins/slick.gantt.rangedecorator.js"></script>
    <script src="../plugins/slick.cellexternalfullcopymanager.js"></script>
    <script src="../controls/slick.columnpicker.js"></script>
    <script src="../plugins/slick.headermenu.js"></script>
    <script src="../plugins/slick.headerbuttons.js"></script>
    <script src="../lib/jszip.min.js"></script>
    <script src="../lib/excel-gen.js"></script>
    <script src="../lib/FileSaver.js"></script>
    <script src="../controls/slick.pager.js"></script>
    <script src="../plugins/slick.checkboxselectcolumn.js"></script>
    <script src="../plugins/slick.rowselectionmodel.js"></script>
    <script src="../lib/select2.js"></script>
    <script>
        function requiredFieldValidator(value) {
            if (value == null || value == undefined || !value.length) {
                return { valid: false, msg: "This is a required field" };
            } else {
                return { valid: true, msg: null };
            }
        }

        var mps = {
            M: 'manufactory',
            P: 'purchase'
        }


        function toggleFilterRow() {
            grid.setTopPanelVisibility(!grid.getOptions().showTopPanel);
        }

        // top panel
        $(".grid-header .ui-icon")
            .addClass("ui-state-default ui-corner-all")
            .mouseover(function (e) {
                $(e.target).addClass("ui-state-hover")
            })
            .mouseout(function (e) {
                $(e.target).removeClass("ui-state-hover")
            });

        function PopulateSelect(select, dataSource, addBlank) {
            var index, len, newOption;
            if (addBlank) { select.appendChild(new Option('', '')); }
            $.each(dataSource, function (value, text) {
                newOption = new Option(text, value);
                select.appendChild(newOption);
            });
        };

        // stackoverflow.com/questions/2532218
        function pickRandomProperty(obj) {
            var result;
            var count = 0;
            for (var prop in obj)
                if (Math.random() < 1 / ++count)
                    result = prop;
            return result;
        }

        function PopulateSelect(select, dataSource, addBlank) {
            var index, len, newOption;
            if (addBlank) { select.appendChild(new Option('', '')); }
            $.each(dataSource, function (value, text) {
                newOption = new Option(text, value);
                select.appendChild(newOption);
            });
        };

        var TaskNameFormatter = function (row, cell, value, columnDef, dataContext) {
            value = value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
            var spacer = "<span style='display:inline-block;height:1px;width:" + (15 * dataContext["indent"]) + "px'></span> ";
            var idx = dataView.getIdxById(dataContext.id);
            var levelNum = doLevelNum(dataContext["indent"]);
            
            if (data[idx + 1] && data[idx + 1].indent > data[idx].indent) {
                if (dataContext._collapsed) {
                    return spacer + " <span class='toggle expand'></span>&nbsp;" + levelNum + f2000Status(dataContext);
                } else {
                    return spacer + " <span class='toggle collapse'></span>&nbsp;" + levelNum + f2000Status(dataContext);
                }
            } else {
                return spacer + " <span class='toggle'></span>&nbsp;" + levelNum + f2000Status(dataContext);
            }
        };

        function doLevelNum(ix) {
            return " [" + (ix + 1) + "] ";
        }

        function f2000Status(data) {
            return "<a " + (data.state ? "style='color:red'" : "") + ">" + data.f2000 + "</a>";
        }

        var searchString = "";
        var dataView;
        var grid;
        var levelIx = 0;
        var data = [];
        var groups = [[{ "group": "D", "name": "design", "expend": true }]];
        var columns = [
            { id: "num", group: ["D"], expend: true },
            { id: "checked", group: ["D"], expend: true },
            { id: "f2000", name: "no", expend: true, group: ["D"], field: "f2000", width: 220, cssClass: "cell-title", formatter: TaskNameFormatter, editor: Slick.Editors.Text, validator: requiredFieldValidator },
        ];


        for (var i = 0; i < 100; i++) {
            if (i % 7 == 0) {
                groups[0].push({ "group": "D" + i, "name": i / 7 + 1, "expend": true })
            }
            columns.push({ id: "o" + i, name: i % 7 + 1, group: [groups[0][groups[0].length - 1].group], width: 10 });
        }

        var options = {
            editable: true,
            enableAddRow: true,
            enableCellNavigation: true,
            cellHighlightCssClass: "changed",
            cellFlashingCssClass: "current",
            asyncEditorLoading: false,
            frozenColumn: 2,
            headerGroups: groups,
            showHeaderRow: false,
            autoEdit: true,
            rowHeight: 30,
            fileName: function () {
                return "bom.xlsx";
            },
            topPanelHeight: 30
        };

        var percentCompleteThreshold = 0;
        var searchString = "";

        // 过滤
        function myFilter(item, args) {
            if (item.parent != null) {
                var parent = data[item.parent];

                while (parent) {
                    if (parent._collapsed) {
                        return false;
                    }

                    parent = data[parent.parent];
                }
            }

            if (args && args.searchString != "" && item["f2000"].indexOf(args.searchString) == -1) {
                return false;
            }

            if (levelIx && levelIx > 0) {
                return item["indent"] < levelIx;
            }

            return true;
        }

        function f2000Sort(a, b) {
            return a["f2000"] - b["f2000"];
        }

        function CustomerFormatter(row, cell, value, columnDef, dataContext) {
            return "<a   class='btnAddPart  cell-a-btn'></a>"
                + " <a   class='btnDeletePart cell-a-btn' ></a > "
                + value
                + "<a class='cell-a-menu' style='border:1px;color:red;margin:3px;'>操作</a >";
        }

        for (var i = 0; i < columns.length; i++) {
            columns[i].header = {
                menu: {
                    items: [
                        {
                            iconImage: "../images/sort-asc.gif",
                            title: "Sort Ascending",
                            command: "sort-asc"
                        },
                        {
                            iconImage: "../images/sort-desc.gif",
                            title: "Sort Descending",
                            command: "sort-desc"
                        },
                        {
                            title: "Hide Column",
                            command: "hide",
                            disabled: true,
                            tooltip: "Can't hide this column"
                        },
                        {
                            iconCssClass: "icon-help",
                            title: "Filter",
                            command: "filter",
                            content: " <input style='widht:50px;' value='0'></input>"
                        }
                    ]
                }
            };
        }

        // 添加行
        function addRow(row) {
            var current = 5;
            var newRow = { title: "new Title", duration: "1 day" };
            var rowData = grid.getData();
            rowData.splice(current, 0, newRow);
            grid.setData(rowData);
            grid.render();
            grid.scrollRowIntoView(current, false);
        }


        $(function () {
            var indent = 0;
            var parents = [];


            $("#excel").bind("click", function () {
                grid.excel();
            });

            $("#scrollRowIntoView").bind("click", function (e) {
                e.stopPropagation();
                e.preventDefault();
            })

            $("#level").bind("click", function (e) {
                e.stopPropagation();
                e.preventDefault();
            })

            $("#levelOp").change(function (e) {
                var optionVal = $("#levelOp option:selected").val();
                if (optionVal == "ALL") {
                    levelIx = 0;
                } else {
                    levelIx = optionVal;
                }

                updateFilter();
            });

            // 增加行模拟
            $("#addRow").bind("click", function () {
                addRow();
            })

            var lastQ = "";
            var lastIx = -1;
            $("#scrollRowIntoViewQuery").bind("click", function (e) {
                var query = $("#scrollRowIntoViewSearch").val();
                var currentServer = Math.round(Math.random() * (data.length - 1));
                if (lastQ != query) {
                    lastIx = -1;
                    lastQ = query;
                }
                for (var ix = 0; ix < data.length; ix++) {
                    var _i = data[ix]["f2000"] ? data[ix]["f2000"].indexOf(query) : -1;
                    if (ix > lastIx && _i > -1) {
                        lastIx = ix;
                        break;
                    }
                }
                grid.scrollRowIntoView(lastIx);
                grid.flashCell(lastIx, grid.getColumnIndex("f2000"), 100);
            })

            // prepare the data
            for (var i = 0; i < 10000; i++) {
                var d = (data[i] = {});
                var parent;

                if (Math.random() > 0.8 && i > 0) {
                    indent++;
                    parents.push(i - 1);
                } else if (Math.random() < 0.3 && indent > 0) {
                    indent--;
                    parents.pop();
                }

                if (parents.length > 0) {
                    parent = parents[parents.length - 1];
                } else {
                    parent = null;
                }

                d["id"] = "id_" + i;
                d["indent"] = indent;
                d["parent"] = parent;
                d["operator"] = "Task " + i;
                d["f2000"] = "任务" + i % 7 + "_" + i;
                d["f1000"] = "EYA001" + i % 7;
                d["f2136"] = "Keep on going never give up !";
                d["qty"] = i % 7;
                d["createTime"] = '2021-02-24';
                d["mp"] = pickRandomProperty(mps);
                d["state"] = i % 2 == 0;
            }

            // initialize the model
            dataView = new Slick.Data.DataView({ inlineFilters: true });
            dataView.beginUpdate();
            dataView.setItems(data);
            dataView.setFilter(myFilter);
            dataView.endUpdate();

            // initialize the grid
            grid = new Slick.Grid("#myGrid", dataView, columns, options);

            // 编辑
            //可编辑事件失焦前触发的函数
            grid.onBeforeEditCell.subscribe(function (e, args) {
                item = dataView.getItem(args.row);
                if (item.state) {
                    return false;
                }
            });
            //可编辑事件失焦后触发的函数
            grid.onBeforeCellEditorDestroy.subscribe(function (e, args) {
                console.log(item);//这里的args与onBeforeEditCell 中的不同，失去焦点之后会把当前行的对象丢失
                item = {};
            });

            grid.onCellChange.subscribe(function (e, args) {
                dataView.updateItem(args.item.id, args.item);
            });

            // pager 
            var pager = new Slick.Controls.Pager(dataView, grid, $("#pager"));

            var checkboxSelector = new Slick.CheckboxSelectColumn({
                cssClass: "slick-cell-checkboxsel"
            });
            grid.setSelectionModel(new Slick.RowSelectionModel({ selectActiveRow: false }));
            grid.registerPlugin(checkboxSelector);
            var columnpicker = new Slick.Controls.ColumnPicker(columns, grid, options);

            grid.setSelectionModel(new Slick.GanttSelectionModel());
            //grid.setSelectionModel(new Slick.RowSelectionModel());

            grid.registerPlugin(new Slick.AutoTooltips());

            // move the filter panel defined in a hidden div into grid top panel
            $("#inlineFilterPanel")
                .appendTo(grid.getTopPanel())
                .show();

            // wire up the search textbox to apply the filter to the model
            $("#txtSearch,#txtSearch2").keyup(function (e) {
                Slick.GlobalEditorLock.cancelCurrentEdit();

                // clear on Esc
                if (e.which == 27) {
                    this.value = "";
                }

                searchString = this.value;
                updateFilter();
            });

            var h_runfilters = null;

            // wire up the slider to apply the filter to the model
            $("#pcSlider,#pcSlider2").slider({
                "range": "min",
                "slide": function (event, ui) {
                    Slick.GlobalEditorLock.cancelCurrentEdit();

                    if (percentCompleteThreshold != ui.value) {
                        window.clearTimeout(h_runfilters);
                        h_runfilters = window.setTimeout(updateFilter, 10);
                        percentCompleteThreshold = ui.value;
                    }
                }
            });

            function updateFilter() {
                dataView.setFilterArgs({
                    searchString: searchString
                });
                dataView.refresh();
            }

            var temp = columns[1];
            var gp = columns[1].group;
            columns[1] = checkboxSelector.getColumnDefinition();
            columns[1].group = gp;
            columns[1].expend = true;

            // set keyboard focus on the grid
            grid.getCanvasNode().focus();
            // https://www.cnblogs.com/fszz/articles/5655154.html
            var copyExtManager = new Slick.CellExternalFullCopyManager();
            //grid.registerPlugin(copyManager);
            grid.registerPlugin(copyExtManager);

            // 自定表头按钮
            var headerMenuPlugin = new Slick.Plugins.HeaderMenu({});

            headerMenuPlugin.onBeforeMenuShow.subscribe(function (e, args) {
                var menu = args.menu;

            });

            headerMenuPlugin.onCommand.subscribe(function (e, args) {
                if (args.command == "filter") {
                    searchString = args.item.filterValue;
                    Slick.GlobalEditorLock.cancelCurrentEdit();
                    dataView.refresh();
                }
            });

            grid.registerPlugin(headerMenuPlugin);

            // checkbox
            var checkboxSelector = new Slick.CheckboxSelectColumn({
                cssClass: "slick-cell-checkboxsel"
            });

            grid.onAddNewRow.subscribe(function (e, args) {
                var item = {
                    "id": "new_" + (Math.round(Math.random() * 10000)),
                    "indent": 0,
                    "title": "New task",
                    "duration": "1 day",
                    "percentComplete": 0,
                    "start": "01/01/2009",
                    "finish": "01/01/2009",
                    "effortDriven": false
                };
                $.extend(item, args.item);
                dataView.addItem(item);
            });


            // key ctrl+a / ctrl+z
            grid.onKeyDown.subscribe(function (e) {

                // select all rows on ctrl-a
                if (!(e.which == 65 || e.which == 90 || e.which == 70) || !e.ctrlKey) {
                    return false;
                }

                if (e.which == 65) {
                    var rows = [];
                    for (var i = 0; i < dataView.getLength(); i++) {
                        rows.push(i);
                    }
                    grid.setSelectedRows(rows);
                    e.preventDefault();
                }

                if (e.which == 90) {
                    var rows = [];
                    grid.setSelectedRows(rows);
                    e.preventDefault();
                }

                if (e.which == 70) {
                    e.preventDefault();
                }

            });


            // tree toggle
            grid.onClick.subscribe(function (e, args) {
                if ($(e.target).hasClass("toggle")) {
                    var item = dataView.getItem(args.row);
                    if (item) {
                        if (!item._collapsed) {
                            item._collapsed = true;
                        } else {
                            item._collapsed = false;
                        }

                        dataView.updateItem(item.id, item);
                    }
                    e.stopImmediatePropagation();
                }
            });

            // contextMenu
            grid.onContextMenu.subscribe(function (e) {
                e.preventDefault();
                var cell = grid.getCellFromEvent(e);
                $("#contextMenu")
                    .data("row", cell.row)
                    .css("top", e.pageY)
                    .css("left", e.pageX)
                    .show();
                $("body").one("click", function () {
                    $("#contextMenu").hide();
                });
            });

            // wire up model events to drive the grid
            dataView.onRowCountChanged.subscribe(function (e, args) {
                grid.updateRowCount();
                grid.render();
            });

            dataView.onRowsChanged.subscribe(function (e, args) {
                grid.invalidateRows(args.rows);
                grid.render();
            });

            var h_runfilters = null;

            // wire up the slider to apply the filter to the model
            $("#pcSlider").slider({
                "range": "min",
                "slide": function (event, ui) {
                    Slick.GlobalEditorLock.cancelCurrentEdit();

                    if (percentCompleteThreshold != ui.value) {
                        window.clearTimeout(h_runfilters);
                        h_runfilters = window.setTimeout(dataView.refresh, 10);
                        percentCompleteThreshold = ui.value;
                    }
                }
            });
            grid.setOptions({ autoEdit: true });
            // wire up the search textbox to apply the filter to the model
            $("#txtSearch").keyup(function (e) {
                Slick.GlobalEditorLock.cancelCurrentEdit();

                // clear on Esc
                if (e.which == 27) {
                    this.value = "";
                }

                searchString = this.value;
                dataView.refresh();
            })
        })
    </script>
</body>

</html>